package cn.lycode.system.service.impl;

import cn.lycode.common.core.domain.model.ConditionDTO;
import cn.lycode.common.core.domain.model.SelectIdsDTO;
import cn.lycode.common.core.service.Treeable;
import cn.lycode.common.enums.ErrorEnum;
import cn.lycode.common.enums.TrueFalseEnum;
import cn.lycode.common.utils.Convert;
import cn.lycode.common.utils.StringUtils;
import cn.lycode.system.constant.SystemConstant;
import cn.lycode.system.domain.dto.sysdept.SysDeptAddDTO;
import cn.lycode.system.domain.dto.sysdept.SysDeptUpDTO;
import cn.lycode.system.domain.entity.SysDept;
import cn.lycode.system.domain.vo.DeptTreeVO;
import cn.lycode.system.domain.vo.SysDeptVO;
import cn.lycode.system.mapper.SysDeptMapper;
import cn.lycode.system.mapper.SysUserMapper;
import cn.lycode.system.service.SysDeptService;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

/**
 * @Title: SysDeptServiceImpl
 * @Author lyg
 * @description:
 */
@Service
@RequiredArgsConstructor
public class SysDeptServiceImpl implements SysDeptService {
    private final SysDeptMapper deptMapper;
    private final SysUserMapper userMapper;


    @Override
    public List<SysDeptVO> list() {
        List<SysDept> sysDeptList = deptMapper.selectDeptList(new ConditionDTO());
        List<SysDeptVO> deptVOS = new ArrayList<>();
        for (SysDept sysDept : sysDeptList) {
            SysDeptVO sysDeptVO = new SysDeptVO();
            BeanUtils.copyProperties(sysDept, sysDeptVO);
            deptVOS.add(sysDeptVO);
        }

        return Treeable.buildTreeVO(deptVOS);
    }

    @Override
    public List<DeptTreeVO> getDeptTree(Boolean needSetTotal) {
        List<SysDept> sysDeptList = deptMapper.selectDeptList(new ConditionDTO());
        List<DeptTreeVO> treeVOS = new ArrayList<>();
        for (SysDept sysDept : sysDeptList) {
            DeptTreeVO deptTreeVO = new DeptTreeVO();
            deptTreeVO.setId(sysDept.getId());
            deptTreeVO.setPid(sysDept.getPid());
            deptTreeVO.setDeptName(sysDept.getDeptName());
            deptTreeVO.setSort(Long.valueOf(sysDept.getDeptSort()));
            deptTreeVO.setDeep(Long.valueOf(sysDept.getDeep()));
            treeVOS.add(deptTreeVO);
        }
        if (needSetTotal != null && needSetTotal) {
            //TODO-优化  如果部门特别多，可尝试优化为一次查询
            for (DeptTreeVO treeVO : treeVOS) {
                Long total = deptMapper.selectTotalByDeptId((Long) treeVO.getId());
                treeVO.setUserTotal(total);
            }

        }
        return Treeable.buildTreeVO(treeVOS);
    }

    /**
     * 账户页面查询部门列表树，需要额外的节点： 全部节点， 未设置部门节点
     */
    @Override
    public List<DeptTreeVO> getDeptTreeWithAdditionalNodes() {
        List<DeptTreeVO> deptTree = getDeptTree(true);
        // 创建全部节点
        DeptTreeVO all = createAllNode();
        // 创建未设置部门节点
        DeptTreeVO unset = createUnsetNode();
        deptTree.add(0, all);
        deptTree.add(1, unset);
        return deptTree;
    }

    private DeptTreeVO createUnsetNode() {
        DeptTreeVO unset = new DeptTreeVO();
        unset.setId(SystemConstant.NO_DEPT_TREE_ID);
        unset.setDeptName(SystemConstant.NO_DEPT_TREE_NAME);
        unset.setUserTotal(userMapper.selectNoDeptUserCount());
        return unset;
    }

    private DeptTreeVO createAllNode() {
        DeptTreeVO all = new DeptTreeVO();
        all.setId(SystemConstant.ALL_DEPT_TREE_ID);
        all.setDeptName(SystemConstant.ALL_DEPT_TREE_NAME);
        all.setUserTotal(userMapper.selectAllUserCount());
        return all;
    }

    @Override
    public int add(SysDeptAddDTO dto) {
        SysDept dept = new SysDept();
        BeanUtils.copyProperties(dto, dept);
        if (dto.getPid() == 0) {
            dept.setDeep(1);
            dept.setAncestors("0");
        } else {
            SysDept parentDept = deptMapper.selectDeptById(dto.getPid());
            ErrorEnum.INVALID_ID.assertNotNull(parentDept);
            ErrorEnum.DEPT_LOCKED.assertFalse(TrueFalseEnum.T.equals(parentDept.getIsLock()));
            dept.setAncestors(parentDept.getAncestors() + "," + dept.getPid());
            dept.setDeep(parentDept.getDeep() + 1);
            //更新父节点的:是否拥有子节点字段 为T
            parentDept.setHasChildren(TrueFalseEnum.T);
            deptMapper.updateDept(parentDept);
        }
        return deptMapper.insertDept(dept);
    }


    @Override
    public int update(SysDeptUpDTO dto) {
        SysDept dept = new SysDept();
        BeanUtils.copyProperties(dto, dept);

        SysDept oldDept = deptMapper.selectDeptById(dto.getId());
        ErrorEnum.INVALID_ID.assertNotNull(oldDept);
        SysDept newParentDept = deptMapper.selectDeptById(dto.getPid());

        if (StringUtils.isNotNull(newParentDept) && StringUtils.isNotNull(oldDept)) {
            //设置祖籍列表
            String newAncestors = newParentDept.getAncestors() + "," + dto.getPid();
            String oldAncestors = oldDept.getAncestors();
            dept.setAncestors(newAncestors);
            //把此部门的子部门的祖籍列表前缀都替换成此部门的祖籍列表
            updateDeptChildren(dept.getId(), newAncestors, oldAncestors);
        }

        //把此部门的子部门的祖籍列表前缀都替换成此部门的祖籍列表
        int result = deptMapper.updateDept(dept);

        if (TrueFalseEnum.T.equals(dept.getIsLock()) && StringUtils.isNotEmpty(dept.getAncestors())
                && !StringUtils.equals("0", dept.getAncestors())) {
            // 如果该部门是启用状态，则启用该部门的所有上级部门
            updateParentDeptUnLock(dept);
        }

        return result;
    }

    private void updateParentDeptUnLock(SysDept dept) {
        String ancestors = dept.getAncestors();
        Long[] deptIds = Convert.toLongArray(ancestors);
        deptMapper.updateDeptUnLocked(deptIds);
    }


    @Override
    public SysDeptVO info(Long deptId) {
        SysDept sysDept = deptMapper.selectDeptById(deptId);
        ErrorEnum.INVALID_ID.assertNotNull(sysDept);
        SysDeptVO sysDeptVO = new SysDeptVO();
        BeanUtils.copyProperties(sysDept, sysDeptVO);
        return sysDeptVO;
    }

    @Override
    public boolean checkDeptExistUser(SelectIdsDTO dto) {
        ErrorEnum.INVALID_ID.assertFalse(dto.getIds().isEmpty());
        int result = deptMapper.checkDeptExistUser(dto.getIds());
        return result > 0;
    }

    @Override
    public boolean hasChildByDeptIds(SelectIdsDTO dto) {
        ErrorEnum.INVALID_ID.assertFalse(dto.getIds().isEmpty());
        int result = deptMapper.hasChildByDeptIds(dto.getIds());
        return result > 0;
    }

    @Override
    public int remove(SelectIdsDTO dto) {
        ErrorEnum.INVALID_ID.assertFalse(dto.getIds().isEmpty());
        return deptMapper.removeByIds(dto.getIds());
    }




    /**
     * 修改子元素关系
     *
     * @param deptId       被修改的部门ID
     * @param newAncestors 新的父ID集合
     * @param oldAncestors 旧的父ID集合
     */
    public void updateDeptChildren(Long deptId, String newAncestors, String oldAncestors) {
        List<SysDept> children = deptMapper.selectChildrenDeptById(deptId);
        for (SysDept child : children) {
            child.setAncestors(child.getAncestors().replaceFirst(oldAncestors, newAncestors));
        }
        if (children.size() > 0) {
            deptMapper.updateDeptChildren(children);
        }
    }

}
